package com.hjy.core.codec;

import com.hjy.common.entity.RpcRequest;
import com.hjy.common.entity.RpcResponse;
import com.hjy.common.enumeration.PackageType;
import com.hjy.common.enumeration.RpcError;
import com.hjy.common.exception.RpcException;
import com.hjy.core.serializer.CommonSerializer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;

import java.util.List;

/**
 * 自定义协议
 * <p><p/>
 * +---------------+---------------+-----------------+-------------+
 * |  Magic Number |  Package Type | Serializer Type | Data Length |
 * |    4 bytes    |    4 bytes    |     4 bytes     |   4 bytes   |
 * +---------------+---------------+-----------------+-------------+
 * |                          Data Bytes                           |
 * |                   Length: ${Data Length}                      |
 * +---------------------------------------------------------------+
 */
public class CommonCodec extends ByteToMessageCodec<Object> {

    private static final int MAGIC_NUMBER = 0xCAFEBABE;

    private final CommonSerializer serializer;

    public CommonCodec(CommonSerializer serializer) {
        this.serializer = serializer;
    }

    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
        // 魔数
        out.writeInt(MAGIC_NUMBER);
        // 对象类型
        if (msg instanceof RpcRequest) {
            out.writeInt(PackageType.REQUEST_PACK.getCode());
        } else {
            out.writeInt(PackageType.RESPONSE_PACK.getCode());
        }
        //序列化方式
        out.writeInt(serializer.getCode());
        byte[] bytes = serializer.serialize(msg);
        // 信息长度
        out.writeInt(bytes.length);
        // 内容
        out.writeBytes(bytes);

    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        // 魔数
        int magic = in.readInt();
        if (magic != MAGIC_NUMBER) {
            System.err.println("不识别的协议包: " + magic);
            throw new RpcException(RpcError.UNKNOWN_PROTOCOL);
        }
        // 对象类型
        int packageCode = in.readInt();
        Class<?> packageClass;
        if (packageCode == PackageType.REQUEST_PACK.getCode()) {
            packageClass = RpcRequest.class;
        } else if (packageCode == PackageType.RESPONSE_PACK.getCode()) {
            packageClass = RpcResponse.class;
        } else {
            System.err.println("不识别的数据包: " + packageCode);
            throw new RpcException(RpcError.UNKNOWN_PACKAGE_TYPE);
        }
        // 反序列化方式
        int serializerCode = in.readInt();
        CommonSerializer serializer = CommonSerializer.getByCode(serializerCode);
        if (serializer == null) {
            System.err.println("不识别的反序列化器: " + serializerCode);
            throw new RpcException(RpcError.UNKNOWN_PACKAGE_TYPE);
        }
        // 内容长度
        int length = in.readInt();
        byte[] bytes = new byte[length];
        in.readBytes(bytes);
        Object obj = serializer.deserialize(bytes, packageClass);
        out.add(obj);
    }
}
